package com.minimalist.lindi.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.entity.basic.enums.RespEnum;
import com.minimalist.common.entity.basic.enums.StatusEnum;
import com.minimalist.common.entity.basic.vo.file.FileUpdateStatusVO;
import com.minimalist.common.entity.basic.vo.file.FileVO;
import com.minimalist.common.entity.lindi.enums.LindiNewsEnum;
import com.minimalist.common.entity.lindi.po.LindiNews;
import com.minimalist.common.entity.lindi.vo.news.LindiNewsQueryVO;
import com.minimalist.common.entity.lindi.vo.news.LindiNewsVO;
import com.minimalist.common.feign.client.basic.FileFeignClient;
import com.minimalist.common.response.R;
import com.minimalist.common.utils.TextUtil;
import com.minimalist.common.utils.UnqIdUtil;
import com.minimalist.lindi.mapper.LindiNewsMapper;
import com.minimalist.lindi.service.LindiNewsService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 林地指标交易平台_新闻表 服务层实现。
 *
 * @author 11987
 * @since 2025-04-02
 */
@Service
public class LindiNewsServiceImpl extends ServiceImpl<LindiNewsMapper, LindiNews> implements LindiNewsService{

    @Autowired
    private LindiNewsMapper mapper;

    @Autowired
    private FileFeignClient fileFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addNews(LindiNewsVO newsVO){
        LindiNews news = BeanUtil.copyProperties(newsVO, LindiNews.class);
        //新闻ID
        long newsId = UnqIdUtil.uniqueId();
        news.setNewsId(newsId);
        //内容处理 -> 编码
        news.setNewsContent(TextUtil.encode(newsVO.getNewsContent()));
        //插入
        int insertCount = mapper.insert(news, true);
        Assert.isTrue(insertCount > 0, () -> new BusinessException(RespEnum.FAILED.getDesc()));
        //公告相关文件处理
        fileStatusHandler(null, newsVO, StatusEnum.STATUS_1.getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNewsByNewsId(Long newsId){
        //查询新闻
        LindiNews news = mapper.selectNewsByNewsId(newsId);
        Assert.notNull(news, () -> new BusinessException(LindiNewsEnum.ErrorMsgEnum.NONENTITY_NEWS.getDesc()));
        //新闻相关文件处理
        fileStatusHandler(null
                , BeanUtil.copyProperties(news, LindiNewsVO.class)
                , StatusEnum.STATUS_0.getCode());
        //删除新闻
        R<Void> voidR = fileFeignClient.deleteFile(news.getNewsPicFileId());
        Assert.isTrue(voidR.getCode().equals(RespEnum.SUCCESS.getCode())
                , () -> new BusinessException(RespEnum.FAILED.getDesc()));
        mapper.deleteNewsByNewsId(newsId);
    }

    @Override
    public void updateNewsByNewsId(LindiNewsVO newsVO){
        //查询新闻
        LindiNews news = mapper.selectNewsByNewsId(newsVO.getNewsId());
        Assert.notNull(news, () -> new BusinessException(LindiNewsEnum.ErrorMsgEnum.NONENTITY_NEWS.getDesc()));
        LindiNews newNews = BeanUtil.copyProperties(newsVO, LindiNews.class);
        //内容处理 -> 编码
        newNews.setNewsContent(TextUtil.encode(newNews.getNewsContent()));
        //修改
        mapper.updateNewsByNewsId(newNews);
        //公告相关文件处理
        fileStatusHandler(news, BeanUtil.copyProperties(newNews, LindiNewsVO.class), null);
    }

    @Override
    public PageResp<LindiNewsVO> getPageNewsList(LindiNewsQueryVO queryVO){
        //分页查询
        Page<LindiNews> newsPage = mapper.selectPageNewsList(queryVO);
        //数据转换
        List<LindiNewsVO> newsVOList = BeanUtil.copyToList(newsPage.getRecords()
                , LindiNewsVO.class);

        // 批量获取文件信息
        if (CollectionUtil.isNotEmpty(newsVOList)){
            // 收集所有文件ID
            List<Long> fileIds = newsVOList.stream()
                    .map(LindiNewsVO::getNewsPicFileId)
                    .filter(ObjectUtil::isNotNull)
                    .distinct()
                    .collect(java.util.stream.Collectors.toList());

            if (CollectionUtil.isNotEmpty(fileIds)){
                // 批量获取文件信息
                R<List<FileVO>> filesResult = fileFeignClient.getFileListByFileIds(fileIds);
                if (filesResult.getCode().equals(RespEnum.SUCCESS.getCode()) &&
                        CollectionUtil.isNotEmpty(filesResult.getData())){
                    // 创建文件ID到文件对象的映射
                    java.util.Map<Long, FileVO> fileMap = filesResult.getData().stream()
                            .collect(java.util.stream.Collectors.toMap(FileVO::getFileId, file -> file));

                    // 为每个新闻设置对应的文件信息
                    newsVOList.forEach(item -> {
                        if (ObjectUtil.isNotNull(item.getNewsPicFileId())){
                            item.setNewsPicFile(fileMap.get(item.getNewsPicFileId()));
                        }
                    });
                }
            }
        }

        return new PageResp<>(newsVOList, newsPage.getTotalRow());
    }

    @Override
    public LindiNewsVO getNewsByNewsId(Long newsId){
        LindiNews news = mapper.selectNewsByNewsId(newsId);
        //内容 -> 解码
        news.setNewsContent(TextUtil.decode(news.getNewsContent()));
        Assert.notNull(news, () -> new BusinessException(LindiNewsEnum.ErrorMsgEnum.NONENTITY_NEWS.getDesc()));
        LindiNewsVO lindiNewsVO = BeanUtil.copyProperties(news, LindiNewsVO.class);
        if (news.getNewsPicFileId() != null){
            R<FileVO> result = fileFeignClient.getFileByFileId(news.getNewsPicFileId());
            Assert.isTrue(result.getCode() == HttpStatus.HTTP_OK
                    && result.getData() != null, () -> new BusinessException(
                    "获取新闻文件失败"));
            lindiNewsVO.setNewsPicFile(result.getData());
        }
        return lindiNewsVO;
    }

    @Override
    public PageResp<LindiNewsVO> getCarouselNewsList(){
        // 查询置顶且状态正常的新闻，按排序和发布时间倒序，限制前5条
        LindiNewsQueryVO queryVO = new LindiNewsQueryVO();
        queryVO.setStatus(StatusEnum.STATUS_1.getCode());
        queryVO.setPageNum(1L);
        queryVO.setPageSize(5L);

        Page<LindiNews> newsPage = mapper.selectCarouselNewsList(queryVO);
        List<LindiNewsVO> newsVOList = BeanUtil.copyToList(newsPage.getRecords()
                , LindiNewsVO.class);

        // 批量获取文件信息
        if (CollectionUtil.isNotEmpty(newsVOList)){
            List<Long> fileIds = newsVOList.stream()
                    .map(LindiNewsVO::getNewsPicFileId)
                    .filter(ObjectUtil::isNotNull)
                    .distinct()
                    .collect(java.util.stream.Collectors.toList());

            if (CollectionUtil.isNotEmpty(fileIds)){
                R<List<FileVO>> filesResult = fileFeignClient.getFileListByFileIds(fileIds);
                if (filesResult.getCode().equals(RespEnum.SUCCESS.getCode()) &&
                        CollectionUtil.isNotEmpty(filesResult.getData())){
                    java.util.Map<Long, FileVO> fileMap = filesResult.getData().stream()
                            .collect(java.util.stream.Collectors.toMap(FileVO::getFileId, file -> file));

                    newsVOList.forEach(item -> {
                        if (ObjectUtil.isNotNull(item.getNewsPicFileId())){
                            item.setNewsPicFile(fileMap.get(item.getNewsPicFileId()));
                        }
                    });
                }
            }
        }

        return new PageResp<>(newsVOList, newsPage.getTotalRow());
    }

    @Override
    public PageResp<LindiNewsVO> getWebsiteNewsList(LindiNewsQueryVO queryVO){
        // 设置状态为正常
        queryVO.setStatus(StatusEnum.STATUS_1.getCode());

        Page<LindiNews> newsPage = mapper.selectWebsiteNewsList(queryVO);
        List<LindiNewsVO> newsVOList = BeanUtil.copyToList(newsPage.getRecords(), LindiNewsVO.class);

        // 批量获取文件信息
        if (CollectionUtil.isNotEmpty(newsVOList)){
            List<Long> fileIds = newsVOList.stream()
                    .map(LindiNewsVO::getNewsPicFileId)
                    .filter(ObjectUtil::isNotNull)
                    .distinct()
                    .collect(java.util.stream.Collectors.toList());

            if (CollectionUtil.isNotEmpty(fileIds)){
                R<List<FileVO>> filesResult = fileFeignClient.getFileListByFileIds(fileIds);
                if (filesResult.getCode().equals(RespEnum.SUCCESS.getCode()) &&
                        CollectionUtil.isNotEmpty(filesResult.getData())){
                    java.util.Map<Long, FileVO> fileMap = filesResult.getData().stream()
                            .collect(java.util.stream.Collectors.toMap(FileVO::getFileId, file -> file));

                    newsVOList.forEach(item -> {
                        if (ObjectUtil.isNotNull(item.getNewsPicFileId())){
                            item.setNewsPicFile(fileMap.get(item.getNewsPicFileId()));
                        }
                    });
                }
            }
        }

        return new PageResp<>(newsVOList, newsPage.getTotalRow());
    }

    @Override
    public LindiNewsVO getWebsiteNewsDetail(Long newsId){
        LindiNews news = mapper.selectWebsiteNewsDetail(newsId);
        Assert.notNull(news, () -> new BusinessException(LindiNewsEnum.ErrorMsgEnum.NONENTITY_NEWS.getDesc()));

        // 检查新闻状态是否正常
        Assert.isTrue(StatusEnum.STATUS_1.getCode().equals(news.getStatus()),
                () -> new BusinessException("新闻已下线或不存在"));

        // 内容解码
        news.setNewsContent(TextUtil.decode(news.getNewsContent()));

        LindiNewsVO lindiNewsVO = BeanUtil.copyProperties(news, LindiNewsVO.class);

        // 获取封面图片信息
        if (news.getNewsPicFileId() != null){
            R<FileVO> result = fileFeignClient.getFileByFileId(news.getNewsPicFileId());
            if (result.getCode() == HttpStatus.HTTP_OK && result.getData() != null){
                lindiNewsVO.setNewsPicFile(result.getData());
            }
        }

        return lindiNewsVO;
    }

    /**
     * 修改新闻相关的文件信息
     *
     * @param oldNews    新闻(旧)
     * @param newNews    新闻(新)
     * @param fileStatus 文件状态
     */
    private void fileStatusHandler(LindiNews oldNews, LindiNewsVO newNews, Integer fileStatus){
        //公告插入、删除的文件处理
        if (ObjectUtil.isNull(oldNews)){
            //处理富文本编辑器中的图片，富文本内容解码
            String decodeOldContent = TextUtil.decode(newNews.getNewsContent());
            List<String> imgUrlList = TextUtil.getImgUrlByRichText(decodeOldContent);
            if (CollectionUtil.isNotEmpty(imgUrlList)){
                //将富文本中的图片的状态置为已使用
                FileUpdateStatusVO fileUpdateStatusVO = new FileUpdateStatusVO(StpUtil.getLoginIdAsLong(), imgUrlList, fileStatus);
                fileFeignClient.updateStatusByFileUrl(fileUpdateStatusVO);
            }
        } else{
            //旧公告富文本中的图片
            String decodeOldContent = TextUtil.decode(oldNews.getNewsContent());
            List<String> oldContentImgUrlList = TextUtil.getImgUrlByRichText(decodeOldContent);
            //将旧公告富文本中的图片状态置为未使用
            if (CollectionUtil.isNotEmpty(oldContentImgUrlList)){
                FileUpdateStatusVO fileUpdateStatusVO = new FileUpdateStatusVO(
                        StpUtil.getLoginIdAsLong(), oldContentImgUrlList
                        , StatusEnum.STATUS_0.getCode());
                fileFeignClient.updateStatusByFileUrl(fileUpdateStatusVO);
            }
            //新公告富文本中的图片
            String decodeNewContent = TextUtil.decode(newNews.getNewsContent());
            List<String> newContentImgUrlList = TextUtil.getImgUrlByRichText(decodeNewContent);
            //将新公告富文本中的图片状态置为已使用
            if (CollectionUtil.isNotEmpty(newContentImgUrlList)){
                FileUpdateStatusVO fileUpdateStatusVO = new FileUpdateStatusVO(
                        StpUtil.getLoginIdAsLong(), newContentImgUrlList
                        , StatusEnum.STATUS_1.getCode());
                fileFeignClient.updateStatusByFileUrl(fileUpdateStatusVO);
            }
        }
    }
}
